home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Compendium Deluxe 2
/
LSD and 17bit Compendium Deluxe - Volume II.iso
/
a
/
prog
/
asmsrc
/
thesource-7.lha
/
Source
/
DefFunc.lha
/
DefFunc
/
dfcsymtable.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-14
|
12KB
|
548 lines
/*********************************************************
*
* Copyright (c) 1993 Ke Jin
*
* Permission to use, copy, modify, and distribute
* this software and its documentation without fee
* is granted, provided that the author's name and
* this copyright notice are retained.
*
* -----------------------------------------------------
*
* dfcsymtable.c -- symbol table of defunc
*
* public function : getsym();
* getfnctname();
* getarguname();
*
* nameargu();
* initargu();
* namefnct();
* namecnst();
* clrfnct();
* clrfnctall();
* clrcnst();
* clrcnstall();
*
* matha2z();
*
* private variable : sym_table;
* tablen;
*
* private function : top();
* isname();
* clrname();
* clrall();
*
*********************************************************/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include "dfcsymtable.h"
#ifdef __cplusplus
extern "C" { /* for c++ */
#endif
static Symbol_record* sym_table = 0;
/* The defunc system global name-object association table */
#if NeedFunctionPrototypes
Symbol_record* getsym(char *name)
#else
Symbol_record* getsym(name)
char *name;
#endif
/* search for record with the given name from sym_table */
{
Symbol_record* ptr;
if(name==0) return 0;
for(ptr=sym_table; ptr!=0; ptr=(Symbol_record*)ptr->next)
{
if(strcmp(ptr->name, name)==0) break;
}
return ptr;
/* if symbol with name not in sym_table, return will be NULL */
};
#if NeedFunctionPrototypes
char* getfnctname(double (*fnct)())
#else
char* getfnctname(fnct)
double (*fnct)();
#endif
{
Symbol_record* ptr;
for(ptr=sym_table;ptr!=0;ptr=ptr->next)
{
if(ptr->type==fnct_symbol)
{
if(fnct==ptr->content.fnctptr) return ptr->name;
}
}
return 0;
};
#if NeedFunctionPrototypes
char* getarguname(int argidx)
#else
char* getarguname(argidx)
int argidx;
#endif
/* return the name of the argument with specific index */
{
Symbol_record* ptr;
for(ptr=sym_table; ptr!=0; ptr=ptr->next)
{
if(ptr->type==arg_symbol)
{
if(argidx==ptr->content.argidx) return ptr->name;
}
}
return 0;
};
#if NeedFunctionPrototypes
static Symbol_record* top(void)
#else
static Symbol_record* top()
#endif
/* return the top symbol record in the sym_table heap */
{
Symbol_record* ptr;
for(ptr=sym_table; ptr->next!=0; ptr=(Symbol_record*)ptr->next)
{
/* skim over the table, do nothing on it */
};
return ptr;
};
#if NeedFunctionPrototypes
static int isname(char* str)
#else
static int isname(str)
char *str;
#endif
/* Is the string str a legal name? (start with alphabetic character
* followed by alphabetics or numberical characters) */
{
int i;
if(str==0||strlen(str)==0) return 0;
if(!isalpha(str[0])) return 0; /* fail */
for(i=1;i<strlen(str);i++)
{
if(!isalnum(str[i])) return 0; /* fail */
}
return 1; /* true */
};
#if NeedFunctionPrototypes
static int clrname(char* name, Symbol_type type)
#else
static int clrname(name, type)
char* name;
Symbol_type type;
#endif
/* delete a specific name with given type from symbol table */
{
Symbol_record *ptr=sym_table, *newnext;
if(sym_table==0) return 0; /* empty table, no delete action */
if(strcmp(sym_table->name, name)==0&&ptr->type==type)
/* name and type matched with the 1st record */
{
ptr = sym_table;
sym_table = sym_table->next; /* cut out the 1st record */
free(ptr->name);
free(ptr);
return 1;
}
for(ptr=sym_table; ptr->next!=0; ptr=(Symbol_record*)ptr->next)
/* skim through the table */
{
if(strcmp(ptr->next->name, name)==0&&ptr->next->type==type)
/* name and type matched with the next record */
{
newnext=ptr->next->next; /* cut out the next record */
free(ptr->next->name);
free(ptr->next);
ptr->next=newnext;
return 1;
}
}
return 0; /* no matching */
};
#if NeedFunctionPrototypes
int clrfnct(char* name)
{ return clrname(name, fnct_symbol);};
int clrcnst(char* name)
{ return clrname(name, const_symbol);};
#else
int clrfnct(name) char* name;
{ return clrname(name, fnct_symbol);};
int clrcnst(name) char* name;
{ return clrname(name, const_symbol);};
#endif
#if NeedFunctionPrototypes
static int clrall(Symbol_type type)
#else
static int clrall(type)
Symbol_type type;
#endif
/* delete all symbols with specific type from symbol table */
{
Symbol_record* ptr, *newnext;
int i=0;
if(sym_table==0) return 0; /* empty, no delete action */
for(ptr=sym_table;sym_table!=0;ptr=sym_table)
/* always point to 1st record */
{
if(sym_table->type==type) /* type matched with the 1st record */
{
sym_table=sym_table->next; /* cut out the 1st record */
free(ptr->name);
free(ptr);
i++;
}
else break; /* if new 1st record not match, jump out */
}
if(sym_table == 0) return i; /* still have record ? */
for(ptr=sym_table; ptr->next!=0; ptr=(Symbol_record*)ptr->next)
/* skim through the table */
{
if(ptr->next->type==type) /* type matched with next record */
{
newnext = ptr->next->next; /* cut out the next record */
free(ptr->next->name);
free(ptr->next);
ptr->next = newnext;
i++;
}
}
return i;
};
#if NeedFunctionPrototypes
int clrfnctall(void)
{ return clrall(fnct_symbol);};
int clrcnstall(void)
{ return clrall(const_symbol);};
#else
int clrfnctall()
{ return clrall(fnct_symbol);};
int clrcnstall()
{ return clrall(const_symbol);};
#endif
#if NeedFunctionPrototypes
int namefnct(char* str, double (*fnctptr)())
#else
int namefnct(str, fnctptr)
char *str;
double (*fnctptr)();
#endif
/* add a function symbol to the end of sym_table */
{
Symbol_record* ptr=0;
if(!isname(str)||fnctptr==0) return 0;
if(sym_table==0) /* table is empty */
{
if(nameargu("x", "y")<=0) return -1;
}
ptr = getsym(str);
if(ptr==0) /* symbol not exist in sym_table */
{
ptr = top()->next
= (Symbol_record*)malloc(sizeof(Symbol_record));
if(ptr==0)
{
perror("malloc for new function token item");
exit(1);
}
}
else if(ptr->type==arg_symbol)
{
return -1; /* forbiding override argument symbols */
}
ptr->name = (char*)malloc((strlen(str)+1)*sizeof(char));
if(ptr->name==0)
{
perror("malloc for new function token name");
exit(1);
}
strncpy(ptr->name, str, strlen(str)+1);
ptr->type = fnct_symbol;
ptr->content.fnctptr = fnctptr;
return 1;
};
#if NeedFunctionPrototypes
int namecnst(char* str, double number)
#else
int namecnst(str, number)
char *str;
double number;
#endif
/* add a constnat symbol to the end of sym_table */
{
Symbol_record* ptr=0;
if(!isname(str)) return 0;
if(sym_table==0) /* table is empty */
{
if(nameargu("x", "y")<=0) return -1;
}
ptr = getsym(str);
if(ptr==0) /* symbol not exist in sym_table */
{
ptr = top()->next
= (Symbol_record*)malloc(sizeof(Symbol_record));
if(ptr==0)
{
perror("malloc for constant token item");
exit(1);
}
}
else if(ptr->type==arg_symbol)
{
return -1; /* forbiding override argument symbols */
}
ptr->name = (char*)malloc((strlen(str)+1)*sizeof(char));
if(ptr->name==0)
{
perror("malloc for constant token name");
exit(1);
}
strncpy(ptr->name, str, strlen(str)+1);
ptr->type = const_symbol;
ptr->content.value = number;
return 1;
};
#if NeedFunctionPrototypes
int nameargu(char* arg1, char* arg2)
#else
int nameargu(arg1, arg2)
char *arg1, *arg2;
#endif
/* on error return -1, on success return 1, if no change return 0 */
{
if(!isname(arg1)) return 0;
if(!isname(arg2)) arg2 = "_";
if(strcmp(arg1, arg2)==0) return -1; /* stupid */
clrname(arg1, fnct_symbol);
clrname(arg1, const_symbol);
clrname(arg2, fnct_symbol);
clrname(arg2, const_symbol);
if(sym_table==0)
{
sym_table = (Symbol_record*)malloc(sizeof(Symbol_record));
if(sym_table==0)
{
perror("malloc for the 1st argument token item");
exit(1);
}
}
sym_table->name = (char*)malloc((strlen(arg1)+1)*sizeof(char));
if(sym_table->name==0)
{
perror("malloc for the 1st argument token name");
exit(1);
}
strncpy(sym_table->name, arg1, strlen(arg1)+1);
sym_table->type = arg_symbol;
sym_table->content.argidx = 1;
if(sym_table->next==0)
{
sym_table->next = (Symbol_record*)malloc(sizeof(Symbol_record));
if(sym_table->next==0)
{
perror("malloc for the 2nd token token item");
exit(1);
}
}
sym_table->next->name = (char*)malloc((strlen(arg2)+1)*sizeof(char));
if(sym_table->next->name==0)
{
perror("alloc memory for 2nd arguement name");
exit(1);
}
strncpy(sym_table->next->name, arg2, strlen(arg2)+1);
sym_table->next->type = arg_symbol;
sym_table->next->content.argidx = 2;
return 1;
};
#if NeedFunctionPrototypes
int initargu(void)
#else
int initargu()
#endif
/* if no argument names then use default */
{
if(sym_table==0) return nameargu("x", "y");
return 0;
};
static struct {
char* name;
double (*fnctptr)();
} initfnct[] = {
"sin" , sin ,
"cos" , cos ,
"tan" , tan ,
"tg" , tan ,
"asin" , asin ,
"acos" , acos ,
"atan" , atan ,
"atan2", atan2,
"exp" , exp ,
"sinh" , sinh ,
"sh" , sinh ,
"cosh" , cosh ,
"ch" , cosh ,
"tanh" , tanh ,
"th" , tanh ,
"asinh", asinh,
"ash" , asinh,
"acosh", acosh,
"ach" , acosh,
"atanh", atanh,
"ath" , atanh,
"pow" , pow ,
"log" , log ,
"ln" , log ,
"log10", log10,
"log2" , log2 ,
"sqrt" , sqrt ,
"abs" , fabs ,
0 , 0 };
#if NeedFunctionPrototypes
int matha2z(void)
#else
int matha2z()
#endif
/* set up a symbol table include math "a to z" functions */
{
int i=0, j=0;
initargu();
for(i=0;initfnct[i].name!=0;i++)
{
j = j + namefnct(initfnct[i].name, initfnct[i].fnctptr);
}
j = j + namecnst("pi", 2*asin(1.0));
return j;
};
/* codes for debug ------------------------------------------- */
#if NeedFunctionPrototypes
int printrec(Symbol_record* ptr, double x)
#else
int printrec(ptr, x)
Symbol_record* ptr;
double x;
#endif
{
printf("type = %d\n", ptr->type);
if(ptr->name!=0) printf("name = %s\n", ptr->name);
switch(ptr->type)
{
case const_symbol:
printf("value= %f\n", ptr->content.value);
break;
case arg_symbol:
printf("arg[%d] = %s\n", ptr->content.argidx,
getfnctname(ptr->content.fnctptr));
break;
case fnct_symbol:
printf("%s(%f) = %f\n", ptr->name, x, (ptr->content.fnctptr)(x));
break;
default: break;
}
return 0;
};
#if NeedFunctionPrototypes
int printab(double x)
#else
int printab(x)
double x;
#endif
{
Symbol_record* ptr;
int len = 0;
for(ptr=sym_table; ptr!=0; ptr=ptr->next)
{
len ++;
printrec(ptr, x);
}
return len;
};
#ifdef __cplusplus
} /* end for c++ */
#endif